const cheerio = require("cheerio");
const { fetchHtml } = require("./utils");
const source = require("./source");

const getCatalogs = async (params) => {
	let content = await getDeepthHtml(params.url);
	if (!content) {
		return false;
	}
	const result = handlerCatelogs(content);
	return result;
};

const getDeepthHtml = async (url, content = {}) => {
	try {
		let res = await fetchHtml(url);
		if (res) {
			const parse = new URL(url);

			const targetSource = source.find((i) => i.origin === parse.origin);
			if (targetSource) {
				const $ = cheerio.load(res);
				const { wrapContainer, infomation, pagination, redirect } =
					targetSource.catalogs.rules;

				let info = {
					bookName: "",
					author: "",
					image: "",
					categories: "",
					latestChapter: "",
					latestUpdateTime: "",
					description: "",
				};
				const reflect = [
					["bookName", infomation.bookName],
					["author", infomation.author],
					["image", infomation.image],
					["categories", infomation.categories],
					["latestChapter", infomation.latestChapter],
					["latestUpdateTime", infomation.latestUpdateTime],
					["description", infomation.description],
				];

				reflect.forEach(([key, rule]) => {
					let node = $(rule.selector);
					if (rule?.hasOwnProperty("nthchild")) {
						const num = rule.nthchild;
						if (node?.length >= num + 1) {
							node = node.eq(num);
						}
					}
					if (rule.type === "element") {
						if (rule.attr) {
							info[key] = node.attr(rule.attr) || "";
						} else {
							info[key] = node.text() || "";
						}

						if (rule.subPath) {
							info[key] = `${parse.origin}${info[key]}`;
						}
					} else {
						info[key] = node.attr("content");
					}

					// 处理文字信息
					if (rule?.handler) {
						Object.entries(rule.handler).forEach(
							([type, value]) => {
								switch (type) {
									case "replace":
										info[key] = info[key].replace(
											new RegExp(value, "g"),
											rule.handler?.replaceValue || ""
										);
										break;
									default:
										break;
								}
							}
						);
					}
				});

				if (!content.isParse) {
					origin = parse.origin;
					content = {
						isParse: true,
						origin: parse.origin,
						pathname: parse.pathname,
						links: [],
						...info,
					};
				}

				const wrapperContainer = $(wrapContainer.selector);
				wrapperContainer.each((index, element) => {
					let href = $(element).attr("href");
					if (redirect) {
						href = `${parse.pathname}${href}`;
					}
					content.links.push({
						href,
						text: $(element).text(),
					});
				});
				if (redirect) {
					let node = $(redirect.selector);
					if (redirect?.hasOwnProperty("nthchild")) {
						const num = redirect.nthchild;
						if (node?.length >= num + 1) {
							node = node.eq(num);
						}
					}
					const redirectUrl = node.attr("href");
					if (redirectUrl) {
						const nextUrl = `${parse.origin}${redirectUrl}`;

						content = await getDeepthHtml(nextUrl, content);
					}
				}
				if (pagination) {
					const nextPagination = $(pagination.selector).last();

					let nextPath = nextPagination.attr("href");
					let nextButtonName = nextPagination.text();

					if (nextPath && nextButtonName === "下一页") {
						const nextUrl = pagination.fullpath
							? `${parse.origin}${parse.pathname}${nextPath}`
							: `${parse.origin}${nextPath}`;

						content = await getDeepthHtml(nextUrl, content);
					}
				}
			} else {
				return false;
			}
		} else {
			return false;
		}
	} catch (error) {
		return false;
	}

	return content;
};

const handlerCatelogs = (content) => {
	const array = content.links || [];
	// 过滤重复的 href
	const uniqueArray = Array.from(new Set(array.map((item) => item.href))).map(
		(href) => array.find((item) => item.href === href)
	);

	// 按照 xxxx.html 从小到大排序
	uniqueArray.sort((a, b) => {
		const numA = parseInt(a.href.split("/").pop().split(".html")[0]);
		const numB = parseInt(b.href.split("/").pop().split(".html")[0]);
		return numA - numB;
	});

	content.links = uniqueArray;
	content.origins = [
		{
			origin: content.origin,
			pathname: content.pathname,
		},
	];
	return content;
};

module.exports = {
	getCatalogs,
};
